﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using Mono.Cecil;
using CustomTypes.Mono.Extensions;
using CustomTypes.Interfaces;
using devtm.AutoMapper.CustomCode.TemplateAdd;


namespace devtm.AutoMapper.TemplateAdd.Models
{

    [CLSCompliant(false)]
    public class AssemblyBox : TreeViewItem
    {

        internal static byte[] imgAssemblyNamer = devtm.AutoMapper.Properties.Resources.AssemblyName.GetBytes();
        //private HashSet<string> namespaces;
        private Predicate<TypeDefinition> predicate;
        internal IAssemblyDescriptor assembly;
        internal TypeDefinition selectedType;
        HashSet<string> lst = new HashSet<string>();
        internal bool includeType;
        internal string Namespace;
        private bool _loaded;
        private WindowsSelectType form;

        public AssemblyBox(WindowsSelectType form, IAssemblyDescriptor assembly, global::System.IServiceProvider serviceProvider, Predicate<TypeDefinition> predicate, TypeDefinition selectedType, bool includeType)
        {

            this.form = form;
            this.includeType = includeType;
            this.selectedType = selectedType;
            this.predicate = predicate;
            //this.namespaces = namespaces;
            this.assembly = assembly;

            Refresh();

        }

        public AssemblyBox(WindowsSelectType form, IAssemblyDescriptor assembly, global::System.IServiceProvider serviceProvider, Predicate<TypeDefinition> predicate, string @namespace, bool includeType)
        {

            this.form = form;
            this.includeType = includeType;
            this.Namespace = @namespace;
            this.predicate = predicate;
            //this.namespaces = namespaces;
            this.assembly = assembly;

            Refresh();

        }

        public void Refresh()
        {

            this.Items.Clear();
            lst.Clear();

            ContextTitle = new ContainerHeader() { Label = assembly.AssemblyName, ImageSource = imgAssemblyNamer };
            Header = new HeaderCtrl() { Context = ContextTitle };

            var ns = assembly.Namespaces(predicate).OrderBy(c => c).ToList();

            Count = 0;

            foreach (string source in ns)
                //if (namespaces == null || namespaces.Contains(source))
                {
                    Count++;
                    Add(source, assembly);
                }

        }

        public bool ShowSelect()
        {

            if (includeType)
            {

                if (selectedType != null)
                {

                    string assemblyName1 = selectedType.Module.Assembly.Name.Name;
                    string assemblyName2 = assembly.AssemblyName.Split(',')[0];

                    if (assemblyName1 == assemblyName2)
                        foreach (NamespaceBox item in Items)
                            if (selectedType.Namespace.StartsWith(item.Namespace))
                            {
                                item.ShowType();
                                return this.IsExpanded = true;
                            }

                }

            }
            else
                foreach (NamespaceBox item in Items)
                    if (Namespace.StartsWith(item.Namespace))
                        if (item.ShowNamespace())
                            return this.IsExpanded = true;



            return false;

        }


        protected override void OnExpanded(System.Windows.RoutedEventArgs e)
        {
            base.OnExpanded(e);

            if (!_loaded)
                LoadItems();
        }

        public void LoadItems()
        {

            _loaded = true;

            foreach (TreeViewItem item in this.Items)
                if (item is NamespaceBox)
                    (item as NamespaceBox).LoadItems();

        }

        private void Add(string source, IAssemblyDescriptor assembly)
        {

            if (string.IsNullOrEmpty(source))
                return;

            lst.Add(source);

            NamespaceBox c = null;

            string[] nn1 = source.Split('.');

            int index = 0;
            NamespaceBox parent = GetNamespace(nn1, ref index);

            if (parent == null)
            {
                c = new NamespaceBox(nn1, 0, this, predicate);
                AddChild(c);
            }
            else
            {
                //index++;
                parent.Insert(nn1, index, assembly);
            }

        }

        private NamespaceBox GetNamespace(string[] nn1, ref int index)
        {
            string n = nn1[index];
            NamespaceBox retour = null;

            foreach (NamespaceBox item in this.Items)
                if ((item.MyName as string) == n)
                    if (index + 1 < nn1.Length)
                    {
                        index++;
                        retour = item.GetNamespace(nn1, ref index, assembly);

                        if (retour != null)
                            break;

                    }

            return retour;

        }

        internal ContainerHeader ContextTitle { get; set; }

        internal int Count { get; set; }

        internal void Select(TypeBox typeBox)
        {
            TypeSelector s =
                ((this.Parent as TreeView)
                    .Parent as Grid)
                        .Parent as TypeSelector;

            if (s != null)
            {
                s.Select(typeBox);
            }

        }

        internal void Select(NamespaceBox @namespace)
        {
            TypeSelector s =
                ((this.Parent as TreeView)
                    .Parent as Grid)
                        .Parent as TypeSelector;

            if (s != null)
            {
                s.Select(@namespace);
            }

        }

        protected override void OnSelected(System.Windows.RoutedEventArgs e)
        {
            base.OnSelected(e);

            TypeSelector s =
                ((this.Parent as TreeView)
                    .Parent as Grid)
                        .Parent as TypeSelector;

            if (s != null)
            {
                s.Select(this);
            }
        }

        internal WindowsSelectType Form { get { return form; } }

    }

}
